package produce_and_consumer;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @description:
 * @author: walt-zhong
 * @createDate: 2021/9/14
 */
public class ProducerConsumer1 {

    private static final int CAPACITY = 5;
    private static ReentrantLock lock = new ReentrantLock();
    private static Condition fullCondition = lock.newCondition();
    private static Condition emptyCondition = lock.newCondition();

    public static void main(String[] args) {
        Queue<Integer> queue = new LinkedList<>();
        Producer p1 = new Producer(queue,"P1",CAPACITY);
        Producer p2 = new Producer(queue,"P2",CAPACITY);

        Consumer c1 = new Consumer(queue,"C1",CAPACITY);
        Consumer c2 = new Consumer(queue,"C2",CAPACITY);
        Consumer c3 = new Consumer(queue,"C3",CAPACITY);

        p1.start();
        p2.start();
        c1.start();
        c2.start();
        c3.start();
    }

    //生产者
    private static class Producer extends Thread{

        private Queue<Integer> queue;
        private String name;
        private int maxSize;
        int elem = 0;

        public Producer(Queue<Integer> queue,
                        String name,int maxSize){
            super(name);
            this.queue = queue;
            this.name = name;
            this.maxSize = maxSize;
        }

        @Override
        public void run() {
            while(true){
                try {
                    lock.lock();
                    while (queue.size() == maxSize){
                        System.out.println("queue is full Producer [" + name + "] thread wait for consume to consume");
                        fullCondition.await();
                    }

                    //队列没有到最大值就可以生产
                    System.out.println("Producer product value ==>" + elem);
                    queue.offer(elem ++);
                    //通知消费者消费
                    fullCondition.signalAll();
                    emptyCondition.signalAll();
                    Thread.sleep(new Random().nextInt(1000));
                }catch (Exception e){

                }finally {
                   lock.unlock();
                }

            }

        }
    }

    private static class Consumer extends Thread{
        private Queue<Integer> queue;
        private String name;
        private int maxSize;

        public Consumer(Queue<Integer> queue,String name,int maxSize){
            super(name);
            this.queue = queue;
            this.maxSize = maxSize;
            this.name = name;
        }

        @Override
        public void run() {
         while (true){
             try{
                 lock.lock();
                 //队列为空，就阻塞等待生产者生产
                 while (queue.isEmpty()){
                     System.out.println("queue is Empty,Consumer [" + name + "] thread wait for producer to product");
                     emptyCondition.await();
                 }
                 int x = queue.poll();
                 System.out.println("Consumer consume value==>" + x);
                 emptyCondition.signalAll();
                 fullCondition.signalAll();
                 Thread.sleep(new Random().nextInt(1000));

             }catch (Exception e){

             }finally {
                 lock.unlock();
             }
         }

        }
    }
}
